﻿using System;
using System.Collections.Concurrent;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
using Avalonia.VisualTree;

namespace Translate.Helper;

/// <summary>
/// 拖动控件帮助类 可实现指定组件允许拖动
/// </summary>
public class DragControlHelper
{
    private static readonly ConcurrentDictionary<Control, DragModule> DragModules = new();

    public static void StartDrag(Control userControl)
    {
        DragModules.TryAdd(userControl, new DragModule(userControl));
    }

    public static void StopDrag(Control control)
    {
        if (DragModules.TryRemove(control, out var dragModule))
        {
            dragModule.Dispose();
        }
    }


    class DragModule : IDisposable
    {
        /// <summary>
        /// 记录上一次鼠标位置
        /// </summary>
        private Point? _lastMousePosition;

        /// <summary>
        /// 用于平滑更新坐标的计时器
        /// </summary>
        private readonly DispatcherTimer _timer;

        /// <summary>
        /// 标记是否先启动了拖动
        /// </summary>
        private bool _isDragging;

        /// <summary>
        /// 需要更新的坐标点
        /// </summary>
        private PixelPoint? _targetPosition;

        private Control UserControl { get; set; }

        public DragModule(Control userControl)
        {
            UserControl = userControl;
            // 添加当前控件的事件监听
            UserControl.PointerPressed += OnPointerPressed;
            UserControl.PointerMoved += OnPointerMoved;
            UserControl.PointerReleased += OnPointerReleased;

            // 初始化计时器
            _timer = new DispatcherTimer
            {
                Interval = TimeSpan.FromMicroseconds(1)
            };
            _timer.Tick += OnTimerTick;
        }


        /// <summary>
        /// 计时器事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnTimerTick(object sender, EventArgs e)
        {
            var window = UserControl.FindAncestorOfType<Window>();
            if (window != null && window.Position != _targetPosition)
            {
                if (_targetPosition != null)
                {
                    // 更新坐标
                    window.Position = (PixelPoint)_targetPosition;
                }
            }
        }

        private void OnPointerPressed(object sender, PointerPressedEventArgs e)
        {
            if (!e.GetCurrentPoint(UserControl).Properties.IsLeftButtonPressed) return;
            // 启动拖动
            _isDragging = true;
            // 记录当前坐标
            _lastMousePosition = e.GetPosition(UserControl);
            e.Handled = true;
            // 启动计时器
            _timer.Start();
        }

        private void OnPointerReleased(object sender, PointerReleasedEventArgs e)
        {
            if (!_isDragging) return;
            // 停止拖动
            _isDragging = false;
            e.Handled = true;
            // 停止计时器
            _timer.Stop();
        }

        private void OnPointerMoved(object sender, PointerEventArgs e)
        {
            if (!e.GetCurrentPoint(UserControl).Properties.IsLeftButtonPressed) return;

            // 如果没有启动拖动，则不执行
            if (!_isDragging || _lastMousePosition == null) return;

            var currentMousePosition = e.GetPosition(UserControl);
            var offset = currentMousePosition - _lastMousePosition.Value;
            var window = UserControl.FindAncestorOfType<Window>();
            if (window != null)
            {
                // 记录当前坐标
                _targetPosition = new PixelPoint(window.Position.X + (int)offset.X,
                    window.Position.Y + (int)offset.Y);
            }
        }

        public void Dispose()
        {
            _timer.Stop();
            _targetPosition = null;
            _lastMousePosition = null;
        }
    }
}